定义原始数据类型

  • nullundefined 是所有类型的子类型。可以复制给任何类型

  • let arrOfNum: number[] = [1, 2, 3, 4]; // 定义元素类型为数子的数组
    
  • tuple 元组类型

    let user: [string, number] = ['jolly', 30]; // 两项,第一项类型为 string, 第二项类型为 number
    
  • 函数声明

    // 指定参数类型和返回值类型
    function add(x: number, y: number, z?: number): number{
      return x + y;
    }
    let add2 = (x: number, y: number, z?: number): number => {
      return x + y;
    }
    
    let add3: (x: number, y:number) => number = add2;
    
  • Type inference 类型推断

    let s = 'str'; // s 类型判定为 'string'. 不能被赋值为非 'string' 类型的值。
    

interface

  • 定义对象类型及形状
interface Person {
  readonly id: number,
  name: string,
  age?: number
}

// 合法代码
let jolly: Person = {
  name: 'jolly',
  age: 30,
  id: 1 // id不能被修改
}
  • 定义函数类型
interface Count {
  (x: number, y: number): number // 定义参数类型和返回值
}
const sum: Count = (x: number, y: number) => x + y;
  • Indexable type 可索引类型
interface Randmap {
  [propName: string]: string;
}
const map: Randmap = {
  a: 'a',
  b: 'b',
  c: 'c' // 合法
  // d: 1 // 不合法,期望 String
}
  • LIke Array 类型
interface LikeArray {
  [index: number]: string
}
const likeArray: LikeArray = ['a', 'b', 'c']; 
likeArray[0]; // 只能访问,没有其他方法
  • duck typing 鸭子类型
// 定义一个四不像
interface FunWithProps {
  (x: number): number;
  name: string;
}
const a: FunWithProps = (x: number) => { // 传入类型要为 number
  //    return 'x' // 不合法,返回类型应为 number
  return x
}
a.name = 'adf' // 类型要为 string

类和接口

  • public
  • private
    • 只在实例上可以访问,子类上不能访问
  • protected
    • 只在子类上可以访问,实例上不能访问
  • interface 约束类,implements 实现类
interface ClockInterface {
  currentTime: number,
  alert(): void
}
interface GameInterface {
  play(): void
}
// 合法代码
class Cellphone implements ClockInterface, GameInterface {
  currentTime: number = 123;
  alert() {

  }
  play() {

  }
}

interface 约束构造函数

类的类型由两部分组成:

  • 静态类型,这个类本身的类型
  • 实例类型,使用 new 关键字创建的实例的类型

构造函数由约束静态类型,从而得到约束

// 约束静态类型
interface ClockStatic {
  new (h: number, m: number): void;
  time: number
}
// 约束实例类型的属性方法
interface ClockInterface {
  currentTime: number,
  alert(): void
}
// 约束实例类型的属性方法
interface GameInterface {
  play(): void
}

const Cellphone: ClockStatic = class Cellphone implements ClockInterface, GameInterface {
  constructor(h: number, m1: number){

  }
  static time: 12
  currentTime: number = 123;
  alert() {

  }
  play() {

  }
}

泛型

函数和泛型

泛型解决的问题

  • 类型推断不能延伸到函数

    • 泛型是在定义函数和接口的时候,不预先指定类型,而在使用时指定类型的一种特性
    function echo<T>(arg: T): T {
      return arg; // T 是泛型的名称,可随意起名。可以理解为将来由参数类型替代
    }
    const result = echo('str'); // result 类型为 string。T = string
    
    // 泛型可以传入多个值
    function swap<T, U>(tuple: [T, U]): [U, T] {
      return [tuple[1], tuple[0]];
    }
    
    //
    

泛型和接口

react 定义文件学习 泛型和接口

安装 @types/react

使用命令 create-react-app 创建 react 项目,返现并没有 @types/react 于是手动安装

npm i -S @types/react

安装了之后,在 tsx 文件中才能 引入 FunctionComponent 接口,不然会报错 “react 没有导出 FunctionComponent”

用来学习的 ts 源码便是 FunctionComponent 接口的定义

interface FunctionComponent<P = {}> {
  (props: PropsWithChildren<P>, context?: any): ReactElement<any, any> | null;
  propTypes?: WeakValidationMap<P>;
  contextTypes?: ValidationMap<any>;
  defaultProps?: Partial<P>;
  displayName?: string;
}

例:

import { FunctionComponent } from 'react'
interface TestProps {
  title: string,
  desc: string
}

// 将接口 TestProps 传递到函数FunctionComponent中
const Test: FunctionComponent<TestProps> = (props) => {
  return (
    <div>
    <h1>{props.title}</h1>
    <p>{props.desc}</p>
    </div>
  )
}

react ts 定义文件源码得知

  • 泛型的默认值 <P = {}>

  • 类型别名: type

    type PlusType = (x: number, y: number) => number
    let sum: PlusType = (x: numver, y: number) => x + y
    
    // WeakValidationMap 的定义
    type WeakValidationMap<T> = {
            [K in keyof T]?: null extends T[K]
                ? Validator<T[K] | null | undefined>
                : undefined extends T[K]
                ? Validator<T[K] | null | undefined>
                : Validator<T[K]>
        };
    
  • 交叉类型 '&'

    同时要有两个接口中的定义的数据

    interface IName {
      name: string
    }
    type IPerson = IName & { age: number }
    let person: IPerson = { name: 'hello', age: 12 } // 同时要有两个接口中的定义的数据
    // 源码中定义 PropsWithChildren 类型,用到了
    type PropsWithChildren<P> = P & { children?: ReactNode }
    
  • 联合类型 '|' 注意,在typescript 不确定传入的类型是联合类型中的哪种时,我们只能访问两种类型共有的属性和方法。怎样判断是联合类型中的哪种类型,请看后面的 “类型断言”

    let numberOrString: number | string // numberOrString 为 number 或 string 类型
    
  • Partial 功能,接受一个泛型, 将其中的属性或函数变为可选。是 typescript 内置类型

    interface Person {
      name: string,
      age: number
    }
    type PersonOptional = Partial<Person>
    /*PersonOption = interface {
      name?: string,
      age?: number
    }*/
    // Partial 的源码
    type Partial<T> = {
        [P in keyof T]?: T[P]; // ? 表示可选
    };
    
  • extends

    在类型别名 WeakValidationMap 的赋值处,出现了 extends 操作符

    type WeakValidationMap<T> = {
      [K in keyof T]?: null extends T[K]
      ? Validator<T[K] | null | undefined>
        : undefined extends T[K]
          ? Validator<T[K] | null | undefined>
          : Validator<T[K]>
    };
    

    extends 作用是判断一个类型是否满足另一个类型的约束。

    • 进行泛型约束

      interface IWithLength {
        length: number
      }
      
      function echoWithArr<T extends IWithLength>(arg: T): T {
        console.log(arg.length) // 将来传入的参数中,不一定有length。于是需要 extends 进行约束:传入的之中,必须有 length 属性
        return arg;
      }
      
    • 条件类型关键字

      WeakValidationMapextends 的作用便是条件类型关键字,产生一个条件类型。

      type NonType<T> = T extends null | undefined ? never : T // 假如泛型参数 T 为 null 或 undefined, 返回 never;否则返回 T
      // NonType<T> 变为条件类型:是什么类型,看传入的泛型 T 的类型。
      let demo1: NonType<number> // demo1 的类型是 number
      let demo1: NonType<null> // demo1 的类型是 never
      

Partial 的实现

  • keyof 操作符,获取键值
  • in 操作符,用作循环
interface CountryResp {
  name: string;
  area: number;
  population: number;
}
// keyof
type keys = keyof CountryResp // keys = 'name' | 'area' | 'population'
// 在 keys 中的取值
type NameType = CountryResp['name']
type CountryOpt = {
  [p in Keys]?: CountryResp[p]
} 
// CountryOpt = {
//   name?: string;
//   area?: number;
//   population?: number;
// }


// Partial 的源码
type Partial<T> = {
    [P in keyof T]?: T[P];
};
  • 常量类型

    上面注释中的代码

    keys = 'name' | 'area' | 'population'
    

    'name' 'area' 'population' 就是常量类型

    注意下面的代码

    const str = '123' // 用const定义常量, str 类型为 '123' 类型
    let str1 = '123' // str1 类型是 string
    

类型断言

使用 as 操作符实现

function getLength(input: number | string) { // 使用了联合类型(ps:一般不要在 '{' 后面写注释,这里只是方便讲解)
  const str = input as string // 视为 string 类型
  // 通过某个类型特有的属性,判断断言是否成立
  if (str.length) {
    return str.length
  } else {
    const number = input as number // 
    return number.toString().length
  }
}

注意,类型断言不是类型转换,如果 as 后面是一个新的类型,将报错

// 我们将上面的代码中的任何一个 as 后面的类型换为未指定类型
const number = input as boolean // 报错:类型 "string | number" 到类型 "boolean" 的转换可能是错误的...

定义文件

用于 ts 编译时的检查,没有实现真正的代码功能

基础

  • 定义文件命名:xx.d.ts

  • 使用 declare

    declare var JQuery: (selector: string) => any;
    

    如果 JQuery 是通过 <script> 标签引入,不是通过 import 引入,则以上声明可以使 ts 不报错

  • npm 包名为 @types/xx 是声明文件

  • @type/XX 包的创建,需要向 DefinitelyTyped 提交定义文件,需要其审批。社区

  • 默认情况下,node_modules 下面的 @types 包都会被编译器自动加载

高级用法

编写声明文件

type HTTPMethod = 'GET' | 'POST' | 'PATCH' |'DELETE'
declare function myFetch<T = any>(url: string, method: HTTPMethod, data?: any): Promise<T>

declare namespace myFetch {
  const get: <T = any>(url: string) => Promise<T>;
  const post: <T = any>(url: string, data: any) => Promist<T>;
}

export = myFetch // 放入 node_modules 后要添加

可以放入一下文件夹中

node_modules
  |—— @tayps
      |—— myFetch
          |—— index.d.ts

现在,在 ts 文件中写 myFatch 方法时,就可一个获得提示了

注意:

  • 这样做,只是为了在书写 ts 代码时获得良好的提示。实际方法的执行逻辑是没有的,在编译成 js 执行会报错
  • import 导入的文件,实际上是 node_modules/@types/myFetch/index

下面看看,真正使用环境下的目录

注意:

  • ts 声明文件的文件名,应和实际的 js 文件名保持一致(.d.ts是声明文件的固定格式)

知识点总结

  • 基本类型
  • 类型推断
  • interface
  • class
  • 泛型
    • react FunctionComponent 定义文件源码
      • 类型别名
      • 联合类型
      • 交叉类型
      • Partial
        • keyof, in
        • 常量类型
      • extends
  • 类型断言
  • 编写声明文件

内置类型还包括很多

  • Promise ...

学习方法

多看别人的定义文件,尤其是大项目的。

Copyright © imooc-lego (2020 - present) all right reserved,powered by GitbookFile Modify: 2021-06-27 08:04:56

results matching ""

    No results matching ""